package com.test.socket;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * Selector的机制
 * 
 * @author Simple
 * @date 2013-8-21 下午01:28:23
 * @Description TODO
 */
public class MySelector {

  public static final int PORT=10000;

  public static void main(String[] args) {
    try {
      new MySelector().startServer();
    } catch(IOException e) {
      e.printStackTrace();
    }
    Socket socket=new Socket();
    try {
      socket.connect(new InetSocketAddress(InetAddress.getLocalHost(), 10000));
    } catch(UnknownHostException e) {
      e.printStackTrace();
    } catch(IOException e) {
      e.printStackTrace();
    }
  }

  public void startServer() throws IOException {
    int keySize=0;
    @SuppressWarnings("unused")
    int channels=0;
    @SuppressWarnings("unused")
    int currentSelecotr=0;
    // 使用Selector
    Selector selector=Selector.open();
    // 建立Channel，通道实例化的时候都会建立一个对应的Socket
    ServerSocketChannel serverSocketChannel=ServerSocketChannel.open();
    // 绑定Channel对应的Socket到PORT
    serverSocketChannel.socket().bind(new InetSocketAddress(InetAddress.getLocalHost(), PORT));
    // 设置Channel为非阻塞
    serverSocketChannel.configureBlocking(false);
    // 把Channel注册到Selector，返回一个Key
    SelectionKey key=serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
    printKeyInfo(key);
    while(true) {
      System.out.println("starting select");
      // 通知事件
      keySize=selector.select();
      // >0有事件发生
      if(keySize > 0) {
        System.out.println("after select operation:" + keySize);
        // 传回的一组keys
        Set<SelectionKey> selectedKeys=selector.selectedKeys();
        Iterator<SelectionKey> it=selectedKeys.iterator();
        while(it.hasNext()) {
          key=it.next();
          printKeyInfo(key);
          System.out.println("key in select:" + selector.keys().size());
          // 一个key被处理完成后，就都被从ready key列表中移除
          it.remove();
          // 如果这个key是可接受的
          if(key.isAcceptable()) {
            ServerSocketChannel _serverSocketChannel=(ServerSocketChannel)key.channel();
            SocketChannel _socketChannel=_serverSocketChannel.accept();// ?
            @SuppressWarnings("unused")
            Socket _socket=_socketChannel.socket();
            _socketChannel.configureBlocking(false);
            _socketChannel.register(selector, SelectionKey.OP_READ | SelectionKey.OP_WRITE);
          } else {
            System.out.println("not acceptable");
          }
        }
      } else {
        System.out.println("Select finished without any keys");
      }
    }
  }

  private static void printKeyInfo(SelectionKey sk) {
    String s=new String();
    s="Att: " + (sk.attachment() == null ? "no" : "yes");
    s+=", Read: " + sk.isReadable();
    s+=", Acpt: " + sk.isAcceptable();
    s+=", Cnct: " + sk.isConnectable();
    s+=", Wrt: " + sk.isWritable();
    s+=", Valid: " + sk.isValid();
    s+=", Ops: " + sk.interestOps();
    System.out.println(s);
  }
}
